﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using Crawler.Data;
using Crawler.Stuff;

namespace Crawler.Reports
{
    public class ReportStore
    {
        public static ReportStore New(string summary) { return new ReportStore(summary); }
        public static ReportStore Last()
        {
            var dc = new ReportDataContext();
            var report = dc.Reports.OrderByDescending(r => r.StartDate).FirstOrDefault();
            return report == null ? null : new ReportStore(report);
        }

        public Report Report { get; private set; }
        public IEnumerable<Request> FailedReqests { get; private set; }

        private readonly ReportDataContext _dc;
        private bool IsFailed;

        private ReportStore() { }

        private ReportStore(Report report)
        {
            Report = report;
            FailedReqests = new List<Request>();
            foreach (var fr in report.FailedRequests)
            {
                ((List<Request>)FailedReqests).Add(DeserializeRequset(fr.RequestData.ToArray()));
            }
        }

        private ReportStore(string summary)
        {
            FailedReqests = new List<Request>();
            _dc = new ReportDataContext();
            var report = new Report { StartDate = DateTime.Now, Summary = summary };
            _dc.Reports.InsertOnSubmit(report);
            _dc.SubmitChanges();
            Report = _dc.Reports.Single(r => r.Id == report.Id);
        }

        public void UpdateProperties()
        {
            _dc.SubmitChanges();
        }

        public void Finish()
        {
            Report.EndDate = DateTime.Now;
            Report.IsSuccesfull = !IsFailed;
            _dc.SubmitChanges();
        }

        public void AddFailedRequest(Request request)
        {
            IsFailed = true;
            var fr = new FailedRequest { ReportId = Report.Id, RequestData = SerializeRequest(request) };
            _dc.FailedRequests.InsertOnSubmit(fr);
            _dc.SubmitChanges();
        }

        public static byte[] SerializeRequest(Request request)
        {
            var ms = new MemoryStream();
            var fr = new BinaryFormatter();
            try
            {
                fr.Serialize(ms, request);
            }
            catch (Exception e)
            {
                //LogError
            }
            ms.Flush();
            byte[] b = ms.ToArray();
            ms.Close();
            return b;
        }

        public static Request DeserializeRequset(byte[] data)
        {
            var ms = new MemoryStream(data);
            var fr = new BinaryFormatter();
            Request r = null;
            try
            {
                r = (Request)fr.Deserialize(ms);
            }
            catch (Exception e)
            {
                //LogError
            }
            ms.Close();
            return r;
        }


    }
}
